#define ADRENALIN_EXPORTS

#include "../include/Timer.h"

Adrenalin::Timer*	Adrenalin::Singleton<Adrenalin::Timer>::_pInstance = NULL;

namespace Adrenalin
{
	Timer::Timer(void)
		: _min(99999), _max(0), _average(0)
	{
		::QueryPerformanceFrequency((LARGE_INTEGER*)&_ticksPerSecond);

		_currentTime       = _lastTime = _lastFPSUpdate = 0;
		_numFrames         = 0;
		_runningTime       = _timeElapsed = _fps = 0.0f;
		_fpsUpdateInterval = _ticksPerSecond >> 1;
		_timer				= false;

		WRITELOG(L"Timer created", LOG_INFO);
	}
	//-----------------------------------------------------------------------------------------
	Timer::~Timer(void)
	{
		WRITELOG(L"Timer closed", LOG_INFO);
	}
	//-----------------------------------------------------------------------------------------
	EResult Timer::Start(void)
	{
		if(_timer) {
			return RUNNING;
		}
		
		::QueryPerformanceCounter( (LARGE_INTEGER*)&_lastTime);
		_timer = true;
		
		WRITELOG(L"Timer started", LOG_INFO);
		return OK;
	}//Start
	//-----------------------------------------------------------------------------------------
	EResult	Timer::Stop(void)
	{
		if(!_timer) {
			return NOTRUNNING;
		}

		__int64 stopTime = 0;

		::QueryPerformanceCounter((LARGE_INTEGER*)&stopTime);
    
		_runningTime += (float)(stopTime - _lastTime) / (float)_ticksPerSecond;
		_timer = false;

		WRITELOG(L"Timer stopped", LOG_INFO);
		return OK;
	}//Stop
	//-----------------------------------------------------------------------------------------
	EResult Timer::Update(void)
	{
		if (!_timer) {
			return NOTRUNNING;
		}

		::QueryPerformanceCounter((LARGE_INTEGER*)&_currentTime );
	    
		_timeElapsed  = (float)(_currentTime - _lastTime) / (float)_ticksPerSecond;
		_runningTime += _timeElapsed;

		_numFrames++;

		if(_currentTime - _lastFPSUpdate >= _fpsUpdateInterval)
		{
			float fCurrentTime = (float)_currentTime / (float)_ticksPerSecond;
			float fLastTime = (float)_lastFPSUpdate / (float)_ticksPerSecond;
	        
			_fps = (float)_numFrames / (fCurrentTime - fLastTime);
			if( _fps > 1 ) {_min = min(_min,_fps); };
			_max = max(_max,_fps);
			_average = (_average + _fps) / 2;

			_lastFPSUpdate = _currentTime;
			_numFrames = 0;
		}

		_lastTime = _currentTime;
		return OK;
	}//UpdateTimer
	//-----------------------------------------------------------------------------------------
};//namespace